package com.xframe.xdal.core.model.sqlbuilder.proc;

import com.xframe.xdal.core.constant.DalConstants;
import com.xframe.xdal.core.handler.HandlerColumnMapManage;
import com.xframe.xdal.core.model.mapping.IRelation;
import com.xframe.xdal.core.model.mapping.ITableInfo;
import com.xframe.xdal.core.model.sqlbuilder.BaseSqlBuilder;
import com.xframe.xdal.core.model.sqlbuilder.BuilderContext;
import com.xframe.xdal.core.model.sqlbuilder.SqlExpression;
import com.xframe.xdal.core.util.StringUtil;
import lombok.extern.log4j.Log4j2;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 功能描述:不带分页的SELECT 查询构造器
 *
 * @author xufeng
 * @version 1.0
 * @date 2022-09-26
 */
@Log4j2
public class SearchSqlBuilder extends BaseSqlBuilder {


    public String getSQL() {
        return "SELECT %s FROM %s WHERE 1 = 1%s";
    }

    private String colPlaceholder = "`";

    private String fromTableString;

    public String getFromTableString(){
        return fromTableString;
    }
    @Override
    public SqlExpression build(BuilderContext context) {
        colPlaceholder = context.getColPlaceholder();
        StringBuilder colstrBuilder = new StringBuilder();
        StringBuilder fromBuilder = new StringBuilder();
        StringBuilder whereBuilder = new StringBuilder();
        List<Object> pList = new ArrayList<>();


        // SQL列名称和属性映射对象的位置关系列表
        HandlerColumnMapManage handlerColumnMapManage = new HandlerColumnMapManage(context.getDataSourceTypeEnums());
        //Map<Integer,HandlerColumn> handlerColumnMap = new HashMap<>();
        // 处理主表 列名称
        buildMainSelect(context,colstrBuilder,colPlaceholder,context.getTableInfo(),handlerColumnMapManage);
        // 构造 from
        fromTableString = buildFrom(context,colPlaceholder,context.getTableInfo());
        fromBuilder.append(fromTableString);

        Map<String,ITableInfo> refTable = new HashMap<>();
        // 处理引用列
        if(context.getTableInfo().getBelongsToMappingList() != null) {
            for (IRelation belongsToMapping : context.getTableInfo().getBelongsToMappingList()) {
                if (context.includeBelongRefName(belongsToMapping.getAs())) {
                    // 处理from列
                    ITableInfo tableInfo = belongsToMapping.getTableInfoByType();
                    if (tableInfo == null) {
                        continue;
                    }
                    refTable.put(belongsToMapping.getAs(), tableInfo);
                    colstrBuilder.append(DalConstants.SQL_SEPARATION);
                    // 处理Select 子句
                    buildSelect(context, colstrBuilder, belongsToMapping, tableInfo, handlerColumnMapManage, true, false, null);
                    // 构造from子句
                    fromBuilder.append(buildFromJoinFrom(context, colPlaceholder, context.getTableInfo(), tableInfo, belongsToMapping));
                }
            }
        }

        // 生成的SQL 是否有包含引用的列表
        boolean isIncludeRefList = false;
        // 处理列表列
        if(context.getTableInfo().getHasManyMappingList() != null) {
            for (IRelation hasManyMapping : context.getTableInfo().getHasManyMappingList()) {
                if (context.includeHasmanyRefName(hasManyMapping.getAs())) {
                    // 处理from列
                    ITableInfo tableInfo = hasManyMapping.getTableInfoByType();
                    if (tableInfo == null) {
                        continue;
                    }
                    refTable.put(hasManyMapping.getAs(), tableInfo);
                    colstrBuilder.append(DalConstants.SQL_SEPARATION);
                    // 处理Select 子句
                    buildSelect(context, colstrBuilder, hasManyMapping, tableInfo, handlerColumnMapManage, false, true, hasManyMapping.getDataType());
                    // 构造from子句
                    fromBuilder.append(buildFromJoinFrom(context, colPlaceholder, context.getTableInfo(), tableInfo, hasManyMapping));
                    isIncludeRefList = true;
                }
            }
        }
        context.setIncludeRefListFlag(isIncludeRefList);
        // 处理查询条件
        context.getConditionValueCollection().builderWhere(context,context.getTableInfo(),refTable,colPlaceholder,whereBuilder,pList);


        String sql = String.format(getSQL(), colstrBuilder, fromBuilder, whereBuilder);
        // 处理排序
        String orderBySql = "";
        if (context.hasDbSortCollection()) {
            if(!isIncludeRefList){
                // 没有引用子表 则构造排序
                orderBySql = DalConstants.SQL_ORDER_BY + context.getDbSortCollection().getOrderBySql(context,context.getTableInfo(),refTable,colPlaceholder);
            }else if(isIncludeRefList && context.getPagerModel() == null){
                // 有子表 但是没有分页
                String orderSql = context.getDbSortCollection().getOrderByComplicatedSql(context,context.getTableInfo(),refTable,colPlaceholder);
                if(!StringUtil.isEmpty(orderSql)){
                    orderBySql = DalConstants.SQL_ORDER_BY + orderSql;
                }
            }
            // 有子表 有分页则不处理 交给分页构造器来处理排序
            context.setRefTable(refTable);
        }else {
            if(isIncludeRefList && context.getPagerModel() == null) {
                // 有子表 但是没有分页
                String orderSql = context.getDbSortCollection().getOrderByComplicatedSql(context, context.getTableInfo(), refTable, colPlaceholder);
                if (!StringUtil.isEmpty(orderSql)) {
                    orderBySql = DalConstants.SQL_ORDER_BY + orderSql;
                }
            }
        }
        return new SqlExpression(sql, orderBySql, pList,handlerColumnMapManage,context.getDataSourceTypeEnums());
    }

}
